//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Globalization;
using System.Web.Caching;
using CommunityServer.Components;
using CommunityServer.ControlPanel.Controls;
using CA = ComponentArt.Web.UI;

namespace CommunityServerStuff.Controls
{

	/// <summary>
	/// Renders a Tab + Submenus based on the tab configuration file.
	/// </summary>
	public class ControlPanelNavigationSidebar : System.Web.UI.WebControls.WebControl
	{
        private CA.NavBar _navBar;
        private CA.ItemLookCollection _itemLooks;
        private bool _expandSinglePath;
        private string _imagesBaseUrl;
        private bool _keyboardEnabled;
        private string _selected;
        private string _fileName;

		public ControlPanelNavigationSidebar() : base()
		{
            Width = new System.Web.UI.WebControls.Unit(210);
            CssClass = "CPNavBar";
            _expandSinglePath = true;
            _imagesBaseUrl = "~/controlpanel/images/controlpanel/";
            _keyboardEnabled = false;
            _fileName = "BlankNavBar.config";
            _selected = null;
		}

        public CA.ItemLookCollection ItemLooks
        {
            get { return _itemLooks; }
            set { _itemLooks = value; }
        }

        public bool ExpandSinglePath
        {
            get { return _expandSinglePath; }
            set { _expandSinglePath = value; }
        }

        public string ImagesBaseUrl
        {
            get { return _imagesBaseUrl; }
            set { _imagesBaseUrl = value; }
        }

        public bool KeyboardEnabled
        {
            get { return _keyboardEnabled; }
            set { _keyboardEnabled = value; }
        }

        /// <summary>
        /// returns the location of the current tab configuration file
        /// </summary>
        public string FileLocation
        {
            get { return Context.Server.MapPath(this.ResolveUrl(FileName)); }
        }
        
        public string Selected
        {
            get
            {
                if (_selected == null)
                    _selected = Context.Items["ControlPanelSelectedNavItem"] as string;

                return _selected;
            }
            set { _selected = value; }
        }

        /// <summary>
        /// Just pass the file name pathed from the root of \ControlPanel\  the
        /// appropriate application url is automatically added
        /// </summary>
        public string FileName
        {
            get
            {
                if (_fileName.StartsWith("~") || _fileName.StartsWith("/"))
                    return _fileName;
                else
                    return string.Concat(SiteUrls.Instance().Locations["ControlPanel"], _fileName);
            }
            set { _fileName = value; }
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            base.CreateChildControls();    

            if (_navBar == null)
            {
                _navBar = new ComponentArt.Web.UI.NavBar();
                _navBar.ID = "SideNavBar";
                _navBar.KeyboardEnabled = KeyboardEnabled;
                _navBar.ExpandSinglePath = ExpandSinglePath;
                _navBar.ImagesBaseUrl = ImagesBaseUrl;
                _navBar.Width = Width;
                _navBar.Height = Height;
                _navBar.CssClass = CssClass;

                if (ItemLooks == null || ItemLooks.Count == 0)
                    ItemLooks = GetDefaultItemLooks();                
                          
                BuildNavBar();
                Controls.Add(_navBar);
                _navBar.ItemLooks.Clear();

                if (ItemLooks != null && ItemLooks.Count > 0)
                {
                    foreach (CA.ItemLook look in ItemLooks)
                        _navBar.ItemLooks.Add(look);
                }
            }
        }

        protected CA.ItemLookCollection GetDefaultItemLooks()
        {
            CA.ItemLookCollection looks = new ComponentArt.Web.UI.ItemLookCollection();
            CA.ItemLook look = new CA.ItemLook();

            look.LookId = "TopItemLook" ;
            look.CssClass = "CPNavBarTopItem";
            look.HoverCssClass = "CPNavBarTopItemHover";
            look.ActiveCssClass = "CPNavBarTopItemActive";
            look.RightIconUrl = "arrow.gif"; 
            look.ExpandedRightIconUrl = "arrow_expanded.gif";
            look.LabelPaddingLeft = new System.Web.UI.WebControls.Unit(15);

            looks.Add(look);
            look = new ComponentArt.Web.UI.ItemLook();

            look.LookId = "TopSelectedItemLook";
            look.CssClass = "CPNavBarTopItem";
            look.HoverCssClass = "CPNavBarTopItemHover";
            look.ActiveCssClass = "CPNavBarTopItemActive";
            look.RightIconUrl = "arrow.gif";
            look.ExpandedRightIconUrl = "arrow_expanded.gif";
            look.LabelPaddingLeft = new System.Web.UI.WebControls.Unit(15);

            looks.Add(look);
            look = new ComponentArt.Web.UI.ItemLook();

            look.LookId = "Level2ItemLook";
            look.CssClass = "CPNavBarLevel2Item";
            look.HoverCssClass = "CPNavBarLevel2ItemHover";
            look.LabelPaddingLeft = new System.Web.UI.WebControls.Unit(15);

            looks.Add(look);
            look = new ComponentArt.Web.UI.ItemLook();

            look.LookId = "Level2SelectedItemLook";
            look.CssClass = "CPNavBarLevel2ItemSelected";
            look.HoverCssClass = "CPNavBarLevel2ItemSelected";
            look.LabelPaddingLeft = new System.Web.UI.WebControls.Unit(15);

            looks.Add(look);

            return looks;
        }

        protected string GetText(Tab t)
        {
            if (t.HasText)
                return t.Text;
            else
                return CommunityServer.ControlPanel.Components.ResourceManager.GetString(t.ResourceName);
        }

        protected string GetText(Tab t, string url)
        {
            return GetText(t);
        }

        /// <summary>
        /// Walks the tab and it's children to see if any of them are currently selected
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        protected SelectedState GetState(Tab t)
        {
            //Check the parent
            if (string.Compare(t.Name, Selected, true, CultureInfo.InvariantCulture) == 0)
                return SelectedState.Selected;

            //Walk each of the child tabs
            if (t.HasChildren)
            {
                foreach (Tab child in t.Children)
                {
                    if (string.Compare(child.Name, this.Selected, true, CultureInfo.InvariantCulture) == 0)
                        return SelectedState.ChildSelected;

                    else if (child.HasChildren)
                    {
                        foreach (Tab cc in child.Children)
                            if (string.Compare(cc.Name, this.Selected, true, CultureInfo.InvariantCulture) == 0)
                                return SelectedState.ChildSelected;
                    }
                }
            }

            //Nothing here is selected
            return SelectedState.Not;
        }

		/// <summary>
		/// Creates the markup for the current TabCollection
		/// </summary>
		/// <returns></returns>
		protected void BuildNavBar()
		{
			CA.NavBarItem parentItem, childItem;

			//Get the tab data
			TabCollection tc = GetTabs();
			SelectedState state;
			String url;
			
			//Walk the parents
			foreach(Tab parent in tc.Tabs)
			{
				//Is this parent enabled? Check Permissions
				if(parent.IsValid(Context))
				{
					parentItem = new CA.NavBarItem();
					parentItem.Text = GetText(parent);

					url = FormatLink(parent);
					if (parent.IsJavaScript)
						parentItem.ClientSideCommand = parent.JavaScript;
					else if (!Globals.IsNullorEmpty(url))
					{
						if (parent.IsModal)
							parentItem.ClientSideCommand = String.Format("Telligent_Modal.Open('{0}', {1}, {2}, {3});", url, parent.ModalWidth, parent.ModalHeight, Globals.IsNullorEmpty(parent.ModalCallback) ? "null" : parent.ModalCallback);
						else
							parentItem.NavigateUrl = url;

						parentItem.Text = GetText(parent, url);
					}

					parentItem.LookId = "TopItemLook";
					parentItem.SelectedLookId = "TopSelectedItemLook";
					_navBar.Items.Add(parentItem);

					//Check to see if/how this is tab is selected
					state = GetState(parent);
					if (state == SelectedState.Selected)
					{
						if (!Globals.IsNullorEmpty(parentItem.NavigateUrl))
						{
							parentItem.LookId = "TopSelectedItemLook";
							_navBar.SelectedItem = parentItem;
						}
						else
							parentItem.Expanded = true;
					}
					else if (state == SelectedState.ChildSelected)
						parentItem.Expanded = true;
					else
						parentItem.Expanded = false;

					//Is there any child tabs? Do we want to display them?
					if(parent.HasChildren)
					{
						foreach(Tab child in parent.Children)
						{
							//Make sure this tab is OK to display
							if(child.IsValid(Context) && child.Enabled && IncludeLink(child) && IsNotFiltered(child))
							{
								childItem = new CA.NavBarItem();
								childItem.Text = GetText(child);

								url = FormatLink(child);
								if (child.IsJavaScript)
									childItem.ClientSideCommand = child.JavaScript;
								else if (!Globals.IsNullorEmpty(url))
								{
									if (child.IsModal)
										childItem.ClientSideCommand = String.Format("Telligent_Modal.Open('{0}', {1}, {2}, {3});", url, child.ModalWidth, child.ModalHeight, Globals.IsNullorEmpty(child.ModalCallback) ? "null" : child.ModalCallback);
									else
										childItem.NavigateUrl = url;

									childItem.Text = GetText(child, url);
								}

								childItem.LookId = "Level2ItemLook";
								childItem.SelectedLookId = "Level2SelectedItemLook";
								parentItem.Items.Add(childItem);
	
                                //if (GetState(child) == SelectedState.Selected)
                                //{
                                //    childItem.LookId = "Level2SelectedItemLook";
                                //    _navBar.SelectedItem = childItem;
                                //}
							}
						}
					}
				}
			}
		}

        /// <summary>
        /// Returns the current instance of the TabCollection
        /// </summary>
        /// <returns></returns>
        protected TabCollection GetTabs()
        {
            string path = FileLocation;

            if (path.StartsWith("/") || path.StartsWith("~"))
                path = Context.Server.MapPath(path);

            TabCollection tc = CSCache.Get(path) as TabCollection;
            if (tc == null)
            {

                tc = (TabCollection)Serializer.ConvertFileToObject(path, typeof(TabCollection));
                CSCache.Max(path, tc, new CacheDependency(path));
            }
            return tc;
        }

        /// <summary>
        /// Allows tabs to removed/not included on other tabs
        /// </summary>
        protected bool IsNotFiltered(Tab child)
        {
            if (child.Filter == null)
                return true;

            string[] filters = child.Filter.Split(',');
            foreach (string filter in filters)
            {
                if (string.Compare(filter, this.Selected, true) == 0)
                    return false;
            }

            return true;

        }

        /// <summary>
        /// Checks to see if the current tab has any Roles and if the current user is a member any
        /// of the roles
        /// </summary>
        protected bool IncludeLink(Tab t)
        {
            if (t.HasRoles)
            {
                string[] roles = t.Roles.Split(';');
                foreach (string role in roles)
                {
                    if (Context.User.IsInRole(role))
                        return true;
                }
                return false;
            }
            return true;
        }

        /// <summary>
        /// Resolves the current url and attempts to append the specified querystring
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        protected string FormatLink(Tab t)
        {
            string url = null;

            if (t.UrlName == null)
            {
                if (!t.HasHref)
                    return null;

                if (t.HasQueryString)
                    url = string.Format(t.Href.Replace('^', '&'), Context.Request.QueryString[t.QueryString]);
                else
                    url = t.Href;
            }
            else
            {
                if (!t.HasParameters)
                    url = FormatUrl(t.UrlName);
                else
                    url = FormatUrl(t.UrlName, t.UrlParameters);
            }

            return ResolveUrl(url);
        }

        protected string FormatUrl(string name)
        {
            return Globals.GetSiteUrls().UrlData.FormatUrl(name);
        }

        protected string FormatUrl(string name, params object[] parameters)
        {
            return Globals.GetSiteUrls().UrlData.FormatUrl(name, parameters);
        }

        /// <summary>
        /// Internal enum used to track if a tab is selected
        /// </summary>
        protected enum SelectedState
        {
            Not,
            Selected,
            ChildSelected
        };
	}
}

